package com.library.picture.books.service.impl;

import com.alibaba.fastjson.JSON;
import com.library.common.utils.StringUtils;
import com.library.picture.books.entity.PictureBooksInfo;
import com.library.picture.books.entity.PictureType;
import com.library.picture.books.service.IPictureBooksInfoService;
import com.library.picture.books.utils.Wapper;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * 绘本管理Service业务层处理
 *
 * @author wanghongjie
 * @date 2022-04-26
 */
@Slf4j
@Service
public class PictureBooksInfoServiceImpl implements IPictureBooksInfoService {
    /**
     * 绘本表
     */
    private static final String PICTURE = "picture";
    @Resource
    private MongoTemplate mongoTemplate;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    public static final String INFO_KEY = "app:info:";

    @Override
    public PictureBooksInfo selectPictureBooksInfoById(String id) {
        return mongoTemplate.findById(id, PictureBooksInfo.class, PICTURE);
    }

    /**
     * 根据绘本编号查询绘本信息
     *
     * @param pictureBookNo 绘本编号
     * @return
     */
    @Override
    public PictureBooksInfo selectPictureBooksInfoByNo(String pictureBookNo) {
        String info = redisTemplate.opsForValue().get(INFO_KEY.concat(pictureBookNo));
        if (StringUtils.isNotEmpty(info)) {
            return JSON.parseObject(info, PictureBooksInfo.class);
        }
        Query query = new Query();
        query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookNo)).is(pictureBookNo));
        PictureBooksInfo pictureBooksInfo = mongoTemplate.findOne(query, PictureBooksInfo.class, PICTURE);
        assert pictureBooksInfo != null;
        updateReadQuantity(pictureBooksInfo);
        redisTemplate.opsForValue().set(INFO_KEY.concat(pictureBookNo), JSON.toJSONString(pictureBooksInfo));
        return pictureBooksInfo;
    }

    /**
     * 更新绘本推荐信息
     *
     * @param pictureBookNo 绘本编号
     * @return
     */
    @Override
    public PictureBooksInfo updateRecommendBooks(String pictureBookNo) {
        Query query = new Query();
        query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookNo)).is(pictureBookNo));
        PictureBooksInfo pictureBooksInfo = mongoTemplate.findOne(query, PictureBooksInfo.class, PICTURE);
        assert pictureBooksInfo != null;
        if (Objects.isNull(pictureBooksInfo.getRecommendBooks()) || pictureBooksInfo.getRecommendBooks().isEmpty()) {
            Query queryType = new Query();
            queryType.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureTypeNo)).is(pictureBooksInfo.getPictureTypeNo()));
            List<PictureBooksInfo> pictureBooksInfos = mongoTemplate.find(queryType, PictureBooksInfo.class, PICTURE);
            Update update = new Update();
            pictureBooksInfos.forEach(booksInfo -> {
                booksInfo.setPages(null);
                booksInfo.setRecommendBooks(null);
            });
            update.set(Wapper.getFieldName(PictureBooksInfo::getRecommendBooks), pictureBooksInfos);
            mongoTemplate.updateFirst(query, update, PICTURE);
        }
        return pictureBooksInfo;
    }

    /**
     * 更新阅读数量
     *
     * @param pictureBooksInfo 阅读数量
     */
    private void updateReadQuantity(PictureBooksInfo pictureBooksInfo) {
        Query query = new Query();
        query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookNo)).is(pictureBooksInfo.getPictureBookNo()));
        Update update = new Update();
        update.set(Wapper.getFieldName(PictureBooksInfo::getReadQuantity), Objects.nonNull(pictureBooksInfo.getReadQuantity()) ? pictureBooksInfo.getReadQuantity() + 1 : 1);
        mongoTemplate.updateFirst(query, update, PICTURE);
    }

    @Override
    public List<PictureBooksInfo> selectPictureBooksInfoList(PictureBooksInfo pictureBooksInfo, Pageable pageable) {
        Query query = new Query();
        if (StringUtils.isNotEmpty(pictureBooksInfo.getPictureBookNo())) {
            query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookNo)).is(pictureBooksInfo.getPictureBookNo()));
        }
        if (StringUtils.isNotEmpty(pictureBooksInfo.getPictureTypeNo())) {
            query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureTypeNo)).is(pictureBooksInfo.getPictureTypeNo()));
        }
        if (StringUtils.isNotEmpty(pictureBooksInfo.getPictureBookName())) {
            Pattern pattern = Pattern.compile("^.*" + pictureBooksInfo.getPictureBookName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookName)).regex(pattern));
        }
        pictureBooksInfo.setTotal(mongoTemplate.count(query, PictureType.class, PICTURE));
        query.with(pageable);
        return mongoTemplate.find(query, PictureBooksInfo.class, PICTURE);
    }

    @Override
    public int insertPictureBooksInfo(PictureBooksInfo pictureBooksInfo) {
        mongoTemplate.save(pictureBooksInfo, PICTURE);
        return 1;
    }

    @Override
    public int updatePictureBooksInfo(PictureBooksInfo pictureBooksInfo) {
        Query query = new Query();
        query.addCriteria(Criteria.where(Wapper.getFieldName(PictureBooksInfo::getPictureBookNo)).is(pictureBooksInfo.getPictureBookNo()));
        Update update = new Update();
        update.set(Wapper.getFieldName(PictureBooksInfo::getPictureBookName), pictureBooksInfo.getPictureBookName());
        update.set(Wapper.getFieldName(PictureBooksInfo::getPictureAudio), pictureBooksInfo.getPictureAudio());
        update.set(Wapper.getFieldName(PictureBooksInfo::getPictureCover), pictureBooksInfo.getPictureCover());
        update.set(Wapper.getFieldName(PictureBooksInfo::getPages), pictureBooksInfo.getPages());
        update.set(Wapper.getFieldName(PictureBooksInfo::getAuthor), pictureBooksInfo.getAuthor());
        update.set(Wapper.getFieldName(PictureBooksInfo::getPictureVideo), pictureBooksInfo.getPictureVideo());
        update.set(Wapper.getFieldName(PictureBooksInfo::getPictureBookIntroduction), pictureBooksInfo.getPictureBookIntroduction());
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, PICTURE);
        log.info("updateResult is {}", JSON.toJSONString(updateResult));
        return (int) updateResult.getMatchedCount();
    }

    @Override
    public int deletePictureBooksInfoByIds(String[] ids) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").in(ids));
        DeleteResult remove = mongoTemplate.remove(query, PictureBooksInfo.class, PICTURE);
        return (int) remove.getDeletedCount();
    }

    @Override
    public int deletePictureBooksInfoById(Long id) {
        return 0;
    }
}